﻿using System;
using System.Drawing;

using OpenTK;
using OpenTK.Graphics;
using OpenTK.Input;

namespace Kepler
{
    class CCamera
    {
        private Vector3 _vecCamPos = new Vector3(0.0f, 0.0f, 0.0f);//Zero;
        private Vector3 _vecMoveDir = Vector3.Zero;
        private Vector3 _vecLookAt = new Vector3(0.0f, 0.0f, 1.0f);
        private Vector3 _vecUp = new Vector3(0.0f, 1.0f, 0.0f);

        private float _fyaw = 0.0f;
        private float _fpitch = 0.0f;
        private float _froll = 0.0f;
        private float _fvel = 0.0f;
        private float _faccel = 10.0f;
        private float _fmaxangular = 5.0f;

        public Matrix4 matRotation = new Matrix4();
        public CCamera()
        {

        }

        private Vector3 GetRight()
        {
            return Vector3.Cross(_vecUp, _vecLookAt);
        }

        public void Update(double dTime/*seconds*/, GameWindow gw)
        {
            float secs = (float)dTime;
            // inputs
            // direction

            if (gw.Keyboard[Key.Up])
            {
                _fpitch += MathHelper.DegreesToRadians(_fmaxangular) * secs;
            }

            if (gw.Keyboard[Key.Down])
            {
                _fpitch += MathHelper.DegreesToRadians(-_fmaxangular) * secs;
            }

            if (gw.Keyboard[Key.Left])
            {
                _fyaw += MathHelper.DegreesToRadians(_fmaxangular) * secs;
            }

            if (gw.Keyboard[Key.Right])
            {
                _fyaw += MathHelper.DegreesToRadians(-_fmaxangular) * secs;
            }

            if (gw.Keyboard[Key.Q])
            {
                _froll += MathHelper.DegreesToRadians(_fmaxangular) * secs;
            }

            if (gw.Keyboard[Key.E])
            {
                _froll += MathHelper.DegreesToRadians(-_fmaxangular) * secs;
            }

            // slows the camera down slowly
            float antiforce = 4.0f;
            float r_secs = secs * antiforce;
            if (r_secs > 1.0f) r_secs = 1.0f;
            _fyaw += -_fyaw * r_secs;
            _fpitch += -_fpitch * r_secs;
            _froll += -_froll * r_secs;

            // calculation a rotation matrix
            Vector3 vRight = GetRight();
            matRotation = Matrix4.Rotate(
            Quaternion.FromAxisAngle(_vecUp, _fyaw) *
            Quaternion.FromAxisAngle(vRight, _fpitch) *
            Quaternion.FromAxisAngle(_vecLookAt, _froll));

            // apply the rotations to our vectors
            _vecLookAt = Vector3.Transform(_vecLookAt, matRotation);
            vRight = Vector3.Transform(vRight, matRotation);
            _vecLookAt.Normalize();
            vRight.Normalize();
            _vecUp = Vector3.Cross(_vecLookAt, vRight);

            ////// calculate movements forward/back
            float accel = 0.0f;
            float maxVelocity = _faccel;
            if (gw.Keyboard[Key.W])
            {
                accel = _faccel;
            }
            if (gw.Keyboard[Key.S])
            {
                accel = -_faccel;
            }
            if (accel == 0.0f)
            {
                accel = -_fvel / 2;
                if (accel >= -0.1f && accel <= 0.1f)
                    accel = 0.0f;
            }

            _vecCamPos = _vecCamPos
                    + (_vecLookAt *
                    (_fvel * secs + 0.5f * accel * secs * secs)
                    );
            _fvel += accel * secs;

            if (Math.Abs(_fvel) > maxVelocity)
                _fvel = Math.Sign(_fvel) * maxVelocity;
            if (_fvel >= -0.2f && _fvel <= 0.2f)
                _fvel = 0.0f;
            //which gives ups our vectors for our lookat
            matRotation = Matrix4.LookAt(_vecCamPos, _vecLookAt * 100.0f, _vecUp);
        }
    }
}

